// 所有图标的基础数据
import iconData from "./data.js";

// canvas api 绘制完成后结束动作
const endingActions = function (ctx, opts={}) {
	if (opts.fill) {
		ctx.fillStyle = opts.fillStyle;
		ctx.fill();
	}
	if (opts.stroke) {
		ctx.strokeStyle = opts.strokeStyle;
		ctx.stroke();
	}
	if (opts.close) {
		ctx.closePath();
		ctx.beginPath();
	}
}

/**
 * 绘制线条
 * ctx: canvas 2d 对象
 * item: 路径对象数据
 * opts: 配置项
 * */
export const line = function (ctx, item, opts={}) {
	let zoom = opts.zoom || 1;
	let points = item.items || [];
	points.forEach((p, ind) => {
		let x = p.x * zoom - opts.translateX, y = p.y * zoom - opts.translateY;
		if (ind == 0 && opts.move) {
			ctx.moveTo(x, y);
		} else {
			ctx.lineTo(x, y);
		}
	});
	endingActions(ctx, opts);
}

// 画圆
export const arc = function (ctx, item, opts={}) {
	let zoom = opts.zoom || 1;
	let arcs = item.items || [];
	arcs.forEach((p, ind) => {
		let x = p.x * zoom - opts.translateX, y = p.y * zoom - opts.translateY, radius = p.radius * zoom;
		let startAngle = p.startAngle || 0;
		let endAngle = p.endAngle || Math.PI * 2;
		let anticlockwise = p.anticlockwise || false;
		ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
		endingActions(ctx, opts);
	});
}

// 画椭圆
export const ellipse = function (ctx, item, opts={}) {
	let zoom = opts.zoom || 1;
	let ellipses = item.items || [];
	ellipses.forEach((p, ind) => {
		let x = p.x * zoom - opts.translateX, y = p.y * zoom - opts.translateY, radiusX = p.radiusX * zoom,
			radiusY = p.radiusY * zoom;
		let startAngle = p.startAngle || 0;
		let endAngle = p.endAngle || Math.PI * 2;
		let midAngle = (startAngle + endAngle) / 2;
		let anticlockwise = p.anticlockwise || 0;
		// API5
		ctx.ellipse(x, y, radiusX, radiusY, 0, startAngle, midAngle, anticlockwise);
		ctx.ellipse(x, y, radiusX, radiusY, 0, midAngle, endAngle, anticlockwise);
		// API 6
//		ctx.ellipse(x, y, radiusX, radiusY, 0, startAngle, endAngle, anticlockwise);
		endingActions(ctx, opts);
	});
}

// 画矩形，可设置带圆角的矩形
export const rect = function (ctx, item, opts={}) {
	let rects = item.items || [];
	rects.forEach((p, ind) => {
		let x = p.x, y = p.y, width = p.width, height = p.height;
		let radius = p.radius || 0;
		let arcItems = {
			items: [
				{
					x: x - (width / 2) + radius,
					y: y - (height / 2) + radius,
					radius: radius,
					startAngle: Math.PI * 1,
					endAngle: Math.PI * 1.5
				},
				{
					x: x + (width / 2) - radius,
					y: y - (height / 2) + radius,
					radius: radius,
					startAngle: Math.PI * 1.5,
					endAngle: Math.PI * 2
				},
				{
					x: x + (width / 2) - radius,
					y: y + (height / 2) - radius,
					radius: radius,
					startAngle: Math.PI * 0,
					endAngle: Math.PI * 0.5
				},
				{
					x: x - (width / 2) + radius,
					y: y + (height / 2) - radius,
					radius: radius,
					startAngle: Math.PI * 0.5,
					endAngle: Math.PI * 1
				}
			]
		};
		let arcOpts = {
			...opts
		};
		let lineOpts = {
			...opts
		};
		let lineItems = [
			[
				{
					x: x - (width / 2) + radius,
					y: y - (height / 2)
				},
				{
					x: x + (width / 2) - radius,
					y: y - (height / 2)
				}
			],
			[
				{
					x: x + (width / 2),
					y: y - (height / 2) + radius
				},
				{
					x: x + (width / 2),
					y: y + (height / 2) - radius
				}
			],
			[
				{
					x: x + (width / 2) - radius,
					y: y + (height / 2)
				},
				{
					x: x - (width / 2) + radius,
					y: y + (height / 2)
				}
			],
			[
				{
					x: x - (width / 2),
					y: y + (height / 2) - radius
				},
				{
					x: x - (width / 2),
					y: y - (height / 2) + radius
				}
			]
		];

		if (!opts.fill) {
			arcOpts.close = true;
			lineOpts.close = true;
		} else {
			lineItems = [
				[
					{
						x: x - (width / 2) + radius,
						y: y - (height / 2)
					},
					{
						x: x + (width / 2) - radius,
						y: y - (height / 2)
					},
					{
						x: x + (width / 2),
						y: y - (height / 2) + radius
					},
					{
						x: x + (width / 2),
						y: y + (height / 2) - radius
					},
					{
						x: x + (width / 2) - radius,
						y: y + (height / 2)
					},
					{
						x: x - (width / 2) + radius,
						y: y + (height / 2)
					},
					{
						x: x - (width / 2),
						y: y + (height / 2) - radius
					},
					{
						x: x - (width / 2),
						y: y - (height / 2) + radius
					}
				]
			];
		}
		arc(ctx, arcItems, arcOpts);
		lineItems.forEach(item => {
			let lineItem = {
				items: item
			};
			line(ctx, lineItem, lineOpts);
		})

	});
}

// 二次贝赛尔曲线
export const quadraticCurveTo = function (ctx, item, opts={}) {
	let zoom = opts.zoom || 1;
	let bezierCurves = item.items || [];
	bezierCurves.forEach((p, ind) => {
		let x = p.x * zoom - opts.translateX, y = p.y * zoom - opts.translateY,
			movex = p.movex * zoom - opts.translateX, movey = p.movey * zoom - opts.translateY,
			cpx = p.cpx * zoom - opts.translateX, cpy = p.cpy * zoom - opts.translateY;
		ctx.moveTo(movex, movey);
		ctx.quadraticCurveTo(cpx, cpy, x, y);
		endingActions(ctx, opts);
	});
}

// 三次贝赛尔曲线
export const bezierCurveTo = function (ctx, item, opts={}) {
	let zoom = opts.zoom || 1;
	let bezierCurves = item.items || [];
	bezierCurves.forEach((p, ind) => {
		let x = p.x * zoom - opts.translateX, y = p.y * zoom - opts.translateY,
			movex = p.movex * zoom - opts.translateX, movey = p.movey * zoom - opts.translateY,
			cp1x = p.cp1x * zoom - opts.translateX, cp1y = p.cp1y * zoom - opts.translateY,
			cp2x = p.cp2x * zoom - opts.translateX, cp2y = p.cp2y * zoom - opts.translateY;
		ctx.moveTo(movex, movey);
		ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
		endingActions(ctx, opts);
	});
}

/**
 * 绘制图片
 * ctx: canvas 2d 对象
 * src: 图片路径
 * size: 绘制尺寸
 * */
export const createPattern = function (ctx, src, size=24) {
	let img = new Image();
	img.src = src;
	img.onload = function (e) {
		ctx.drawImage(img, size, size);
		let pat = ctx.createPattern(img, "no-repeat");
		ctx.fillStyle = pat;
		ctx.fillRect(0, 0, size, size);
	};
	img.onerror = function () {

	};
}

/**
 * 绘制文字
 * ctx: canvas 2d 对象
 * item: 文字数据
 * opts: 配置项
 * */
export const fillText = function (ctx, item, opts={}) {
	let zoom = opts.zoom || 1;
	let texts = item.items || [];

	// font-style normal, italic
	// font-weight normal, bold, bolder, lighter, 100, 200, 300, 400, 500, 600, 700, 800, 900
	// font-size 14px
	// font-family sans-serif, serif, monospace

	// "normal normal 14px sans-serif"

	let fontStyle = item.fontStyle || "normal";
	let fontWeight = item.fontWeight || "normal";
	let fontSize = item.fontSize * zoom || 14 * zoom;
	let fontFamily = item.fontFamily || "sans-serif";

	let stroke = item.stroke || false;

	// left right center start end
	let textAlign = item.textAlign || "center";

	// alphabetic top hanging middle ideographic bottom
	let textBaseline = item.textBaseline || "middle";
	texts.forEach((p, ind) => {
		let text = p.text;
		let x = p.x * zoom - opts.translateX, y = p.y * zoom - opts.translateY;

		fontStyle = p.fontStyle || fontStyle;
		fontWeight = p.fontWeight || fontWeight;
		fontSize = p.fontSize ? p.fontSize * zoom : fontSize;
		fontFamily = p.fontFamily || fontFamily;
		ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;

		ctx.textAlign = p.textAlign || textAlign;

		ctx.textBaseline = p.textBaseline || textBaseline;

		stroke = p.stroke || stroke;

		if (stroke) {
			ctx.strokeStyle = opts.strokeStyle;
			ctx.strokeText(text, x, y);
		} else {
			ctx.fillStyle = opts.fillStyle;
			ctx.fillText(text, x, y);
		}

		ctx.font = `normal normal 14px sans-serif`;
		endingActions(ctx, opts);
	});
}

const typeFuns = {
	"line": line,
	"arc": arc,
	"ellipse": ellipse,
	"quadraticCurve": quadraticCurveTo,
	"bezierCurve": bezierCurveTo,
	"text": fillText,
	"rect": rect
};

/**
 * 绘制图形
 * ctx: canvas 2d 对象
 * name: icon名称
 * opts: 配置项
 * */
export const drawIcon = function (ctx, name, opts={}) {
	let ways = iconData[name];
	if (ways) {
		ways.forEach(item => {
			// 保存当前图层
			ctx.save();

			// 设置描边
			let stroke = true;
			if (typeof item.stroke == "boolean") {
				stroke = item.stroke;
			}
			opts.stroke = stroke;

			// 设置描边样式
			let strokeStyle = item.strokeStyle || opts.color || "#333333";
			if (strokeStyle == "back") {
				strokeStyle = opts.backgroundColor
			}
			opts.strokeStyle = strokeStyle;

			// 设置move起点
			let move = true;
			if (typeof item.move == "boolean") {
				move = item.move;
			}
			opts.move = move;

			let close = item.close || false;
			opts.close = close;

			// 设置填充
			let fill = item.fill || false;
			opts.fill = fill;

			// 设置填充样式
			let fillStyle = item.fillStyle || opts.color || "#333333";
			if (fillStyle == "back") {
				fillStyle = opts.backgroundColor
			}
			opts.fillStyle = fillStyle;

			// 获取绘制方法，开始绘制
			let type = item.type;
			let fun = typeFuns[type];
			ctx.beginPath();

			// 设置绘制线条宽度
			let zoom = opts.zoom || 1;
			let lineWidth = item.lineWidth || 2;
			ctx.lineWidth = lineWidth * zoom;

			// 设置绘制线条端点样式
			ctx.lineCap = "round";
			if (item.lineCap) {
				ctx.lineCap = item.lineCap;
			}

			// 设置绘制线条拐点样式
			ctx.lineJoin = "round";
			if (item.lineJoin) {
				ctx.lineJoin = item.lineJoin;
			}

			ctx.miterLimit = 10;
			if (item.miterLimit) {
				ctx.miterLimit = item.miterLimit;
			}

			// 画布偏移和旋转
			let rotation = item.rotation || 0;
			let translateX = item.translateX || 0, translateY = item.translateY || 0;
			opts.translateX = 1;
			opts.translateY = 0;
			if (rotation != 0) {
				ctx.translate(translateX * zoom, translateY * zoom);
				ctx.rotate(rotation);
				opts.translateX = translateX * zoom + 1;
				opts.translateY = translateY * zoom;
			}

			// 执行绘制方法
			fun(ctx, item, opts);

			// 画布复位
			ctx.translate(0, 0);
			ctx.restore();
		})
	} else {
		let regex = new RegExp(/\.(png|jpe?g|bmp|svg|gif|PNG|JPG|JPEG|BMP|SVG|GIF)$/);
		// 绝对路径和base64码
		let urlRegex = new RegExp(/^(http|data)/);
		if (regex.test(name) || urlRegex.test(name)) {
			let src = name;
			let size = opts.size;
			createPattern(ctx, src, size);
		}
	}
}
